#include "carui.h"
#include "ui_carui.h"
#include "QDebug"
#include<QListWidget>
#include<QTimer>
#include<cmath>
void Carui::closeEvent(QCloseEvent *event)
{
    QString news="Q,"+ID+",courier";

    QNetworkDatagram nw(news.toUtf8(),QHostAddress("127.0.0.1"),12345);
    udp->writeDatagram(nw);
}

Carui::Carui(QWidget *parent,QString nn,QString id,QUdpSocket* udp) :
    QMainWindow(parent),
    ui(new Ui::Carui)
{
    ui->setupUi(this);
    name=nn;
    ID=id;
    this->udp=udp;
    this->udp->setParent(this);
    connect(ui->mapwidget,&Mapwidget::changepos,this,&Carui::changeposact);
    ui->mapwidget->identity=1;
    for(auto i:ui->mapwidget->order)
    {
        ui->listWidget_4->addItem(QString().number(i));
    }
    connect(ui->listWidget_4,&QListWidget::currentTextChanged,this,&Carui::changeorder);
    ui->locationButton_10->setEnabled(false);

    ui->mapwidget->identity=1;
    qDebug() << "UDP socket thread:" << udp->thread();
    qDebug() << "Carui (this) thread:" << this->thread();
    connect(this->udp,&QUdpSocket::readyRead,this,&Carui::Udphandle);
}

Carui::~Carui()
{
    delete ui;
}
void Carui::changeposact()
{
    ui->loc_4->setText("("+QString().setNum(ui->mapwidget->location.x())+","+QString().setNum(ui->mapwidget->location.y())+")");
}

void Carui::on_locationButton_9_clicked()
{
    if (!ui || !ui->mapwidget) {
           qDebug() << "ERROR: ui or ui->mapwidget is null!";
           return; // 避免崩溃
       }
    emit ui->mapwidget->chlocationok(1);
    qDebug() << "`11111";
    QString a="A,"+ID+","+"courier,"+QString().number(ui->mapwidget->location.x())+","+QString().number(ui->mapwidget->location.y())+","+name+","+ui->spinBox_4->text();
    QNetworkDatagram q(a.toUtf8(),QHostAddress("127.0.0.1"),12345);
    qDebug() << udp;
    udp->writeDatagram(q);
    qDebug()<<a;
}



void Carui::Udphandle()
{
    while (udp->hasPendingDatagrams()) { // <--- 必须添加这个循环
        const QNetworkDatagram& responseDatagram = udp->receiveDatagram();
        QString response = responseDatagram.data();
        qDebug() << "Received UDP message:" << response; // 调试输出收到的完整消息
        if(response[0]=='A')   //增加坐标
        {
            QStringList parts = response.split(',');
            for (const QString &part : parts) {
                   qDebug() << part;
               }
            if(parts.size()<7)
            {
                qDebug()<<"error is here";
                return;
            }
            int a=parts[1].toInt();
            QPoint p(parts[3].toInt(),parts[4].toInt());
            if(parts[2]=="merchant")
            {
                emit ui->mapwidget->chmarchantin(a,p);
            }
            else
            {
                emit ui->mapwidget->chcarfreein(a,p);
                emit ui->mapwidget->chcarweight(a,parts[6].toInt());
            }
        }
       else if(response[0]=='D')
        {
            QStringList parts=response.split(',');
            for (const QString &part : parts) {
                   qDebug() << part;
               }
            long long i=parts[1].toLong();
            QPoint p(parts[3].toInt(),parts[4].toInt());
            QPoint p2(parts[5].toInt(),parts[6].toInt());
            int w=parts[7].toInt();
            emit ui->mapwidget->chorderstartin(i,p);
            emit ui->mapwidget->chorderendin(i,p2);
            emit ui->mapwidget->chorderi(i);
            emit ui->mapwidget->chorderin(i,w);

        }
       else if(response[0]=='o'&&response[1]=='k')
        {
            qDebug()<<"start";
             QStringList parts=response.split(',');
             if(ui->listWidget_4->findItems(parts[1],Qt::MatchFlag::MatchExactly).empty())
             ui->listWidget_4->addItem(parts[1]);
        }
        else if(response[0]=='F')
        {
            int flag=0;
            QStringList parts=response.split(',');
            for (int i=2;i<parts.size();i++) {
                   if(parts[i]==ID)
                   {
                       flag=1;
                       break;
                   }
               }
           if(flag)
           {
               ui->listWidget_4->addItem(parts[1]);
               ui->listWidget_4->setEnabled(true);
           }
        }
        else if(response[0]=='O')
        {
            QStringList parts=response.split(',');
            for (const QString &part : parts) {
                   qDebug() << part;
               }
            int i=0;
            for(i=1;i<parts.size();i++)
            {
               long long p=parts[i].toLong();
               emit ui->mapwidget->chcarbuzyin(p,ui->mapwidget->carfree[p]);
               emit ui->mapwidget->chcarfreerm(p);
            }
        }
        else if(response[0]=='R')
        {
            QStringList parts=response.split(',');
            for (const QString &part : parts) {
                   qDebug() << part;
               }
            int i=0;
            for(i=1;i<parts.size();i++)
            {
                long long p=parts[i].toLong();
                emit ui->mapwidget->chcarfreein(p,ui->mapwidget->carbuzy[p]);
                emit ui->mapwidget->chcarbuzyrm(p);
            }
        }
        else if(response[0]=='Q')
        {
            QStringList parts=response.split(',');
           long long d=parts[1].toULong();
           if(parts[2]=="merchant")
           {
               emit ui->mapwidget->chmarchantrm(d);
           }
           else
           {
               ui->mapwidget->carfree.remove(d);
               ui->mapwidget->weight.remove(d);
           }
        }
        else if(response[0]=='C')
        {
            QStringList parts=response.split(',');
            for (const QString &part : parts) {
                   qDebug() << part;
               }
            long long d=parts[1].toULong();
            QPoint p(parts[3].toUInt(),parts[4].toUInt());
            if(parts[2]=="merchant")
            {
                emit ui->mapwidget->chmarchantin(d,p);
            }
            else
            {
                if(ui->mapwidget->carbuzy.find(d)!=ui->mapwidget->carbuzy.end())
                {
                    emit ui->mapwidget->chcarbuzyin(d,p);
                }
                else
                {
                    emit ui->mapwidget->chcarfreein(d,p);
                }
            }
        }
        else if(response.startsWith("finish"))
        {
             QStringList parts=response.split(',');
             long long ordernum=parts[1].toLong();
             if(ordernum==ui->mapwidget->noworder)
             {
                 emit ui->mapwidget->chlocationok(0);
                 emit ui->mapwidget->chroadclear();
                 emit ui->mapwidget->chorderr(ordernum);
                 emit ui->mapwidget->chorderendrm(ordernum);
                 emit ui->mapwidget->chorderstartrm(ordernum);
                 emit ui->mapwidget->chnoworder(-1);
                 ui->listWidget_4->clear();

                 ui->locationButton_10->setEnabled(false);
             }
        }

    } // <--- 循环结束
    emit ui->mapwidget->updateemit(); // 在所有数据报处理完毕后发射更新信号
}
QPair<int, int> Carui::findBoundingGridPointIndices(const QPoint& targetPoint, const QVector<QPoint>& gridPoints, int xTolerance, int yTolerance)
{
    if (gridPoints.size() < 2) {
        qDebug() << "错误：网格点不足，无法找到边界点。";
        return qMakePair(-1, -1);
    }

    QVector<QPair<double, int>> candidatePointsByX; // 存储 {到目标点的距离平方, 索引}

    // 1. 第一遍筛选：根据 X 坐标在容忍范围内进行筛选
    for (int i = 0; i < gridPoints.size(); ++i) {
        const QPoint& p = gridPoints.at(i);
        if (std::abs(static_cast<double>(targetPoint.x()) - p.x()) <= xTolerance) {
            // 计算完整的 2D 距离平方，用于后续排序
            double distSquared = (static_cast<double>(targetPoint.x()) - p.x()) * (static_cast<double>(targetPoint.x()) - p.x()) +
                                 (static_cast<double>(targetPoint.y()) - p.y()) * (static_cast<double>(targetPoint.y()) - p.y());
            candidatePointsByX.append(qMakePair(distSquared, i));
        }
    }

    if (candidatePointsByX.size() < 2) {
        qDebug() << "在 X 容忍范围内没有足够的候选点（" << xTolerance << "）。数量：" << candidatePointsByX.size();
        return qMakePair(-1, -1);
    }

    // 2. 第二遍筛选：在 X 筛选后的点中，根据 Y 坐标在容忍范围内进一步筛选
    QVector<QPair<double, int>> finalCandidates; // 存储 {到目标点的距离平方, 索引}

    for (const auto& candidate : candidatePointsByX) {
        int index = candidate.second;
        const QPoint& p = gridPoints.at(index);

        if (std::abs(static_cast<double>(targetPoint.y()) - p.y()) <= yTolerance) {
            finalCandidates.append(candidate); // 如果通过了 Y 容忍筛选，则将其添加为最终候选点
        }
    }

    if (finalCandidates.size() < 2) {
        qDebug() << "应用 Y 容忍范围（" << yTolerance << "）后没有足够的最终候选点。数量：" << finalCandidates.size();
        return qMakePair(-1, -1);
    }

    // 3. 对最终候选点按其到 targetPoint 的总体 2D 距离进行排序
    //    并选择最近的两个不同点。
    std::sort(finalCandidates.begin(), finalCandidates.end(), [](const QPair<double, int>& a, const QPair<double, int>& b){
        return a.first < b.first;
    });

    int firstIndex = finalCandidates.at(0).second;
    int secondIndex = finalCandidates.at(1).second;

    // 确保找到的两个点是不同的（如果 finalCandidates.size() >= 2，理论上应该不同，但为了健壮性检查一下）
    if (firstIndex == secondIndex) {
        // 这种情况理论上不应该发生，除非同一个点以某种方式被添加了两次。
        qDebug() << "在 X 和 Y 容忍范围内只找到一个不同的点。";
        return qMakePair(-1, -1);
    }
    return qMakePair(firstIndex+1, secondIndex+1);
}
void Carui::getroad(QPoint nowlocal,QPoint finallocal)
{

    QPair<int,int> a=findBoundingGridPointIndices(nowlocal,ui->mapwidget->gridPoints,nowlocal.x(),nowlocal.y());
    QPair<int,int> b=findBoundingGridPointIndices(finallocal,ui->mapwidget->gridPoints,finallocal.x(),finallocal.y());
    int dir=0;//0北 1东北 2东 3东南 4南 5 西南 6 西 7西北
    if(finallocal.y()>nowlocal.y())
    {
        if(finallocal.x()>nowlocal.x())
        {
            dir=1;
        }
        else if(finallocal.x()==nowlocal.x())
            dir=0;
        else
            dir=7;
    }
    else
    {
        if(finallocal.x()>nowlocal.x())
        {
            dir=3;
        }
        else if(finallocal.x()==nowlocal.x())
            dir=4;
        else
            dir=5;
    }
    qDebug()<<a;
    qDebug()<<b;
    int obegin;
    int oend;
    QVector<QPoint>& m=ui->mapwidget->gridPoints;
    QPoint a1=m[a.first-1];
    QPoint a2=m[a.second-1];
    QPoint b1=m[b.first-1];
    QPoint b2=m[b.second-1];
    if(abs(a1.x()-a2.x())<15)
    {
        //同一列
        if(a1.y()>a2.y())
        {
            if(dir<3||dir==7)
            {
                obegin=a.first;
            }
            else
                obegin=a.second;
        }
        else
        {

            if(dir<3||dir==7)
            {
                obegin=a.second;
            }
            else
                obegin=a.first;
        }
    }
    else
    {
        //同一行
        if(a1.x()>a2.x())
        {
            if(dir<4)
            {
                obegin=a.first;
            }
            else
                obegin=a.second;
        }
        else
        {
            if(dir<4)
            {
                obegin=a.second;
            }
            else
                obegin=a.first;
        }
    }
    if(abs(b1.x()-b2.x())<15)
    {
        //同一列
        if(b1.y()>b2.y())
        {
            if(dir<3||dir==7)
            {
                oend=b.second;
            }
            else
                oend=b.first;
        }
        else
        {

            if(dir<3||dir==7)
            {
                oend=b.first;
            }
            else
                oend=b.second;
        }
    }
    else
    {
        //同一行
        if(b1.y()>b2.y())
        {
            if(dir<3||dir==7)
            {
                oend=b.first;
            }
            else
                oend=b.second;
        }
        else
        {

            if(dir<3||dir==7)
            {
                oend=b.second;
            }
            else
                oend=b.first;
        }
    }
    pair<queue<int>, int> re=result().dijkstra(obegin,oend);
    QQueue<QPoint> &r=ui->mapwidget->road;
    //r.clear();
    if(!r.empty()&&r.last()==nowlocal)
    {}
    else
    emit ui->mapwidget->chroadin(nowlocal);
    qDebug()<<nowlocal;
    queue<int>& q=re.first;
    while(!q.empty())
    {
       emit ui->mapwidget->chroadin(m[q.front()-1]);
        q.pop();
    }
    emit ui->mapwidget->chroadin(finallocal);
    //qDebug()<<r.front()<<"dddd";
    emit ui->mapwidget->updateemit();
}


void Carui::on_locationButton_10_clicked()
{
    ui->listWidget_4->setEnabled(false);
    emit ui->mapwidget->chroadclear();
    getroad(ui->mapwidget->location,orderstart);
    getroad(orderstart,orderfinal);
    lc=ui->mapwidget->location;
    if(ui->mapwidget->road.empty())
        return;
    //qDebug()<<ui->mapwidget->road.front()<<"over";
  //  ui->mapwidget->road.pop_front();
    rd=ui->mapwidget->road;
    rd.pop_front();
    next=rd.front();
    QString news="O,"+QString().number(ui->mapwidget->noworder)+","+ID;
    QNetworkDatagram nw(news.toUtf8(),QHostAddress("127.0.0.1"),12345);
    udp->writeDatagram(nw);
    tm=new QTimer(this);
    qDebug()<<next<<"here";

    connect(tm,&QTimer::timeout,this, [&](){
        qDebug()<<lc<<next<<orderfinal;
        if(flag&&ui->mapwidget->location==orderfinal)
        {
            QString news="finish,"+QString().number(ui->mapwidget->noworder);
            QNetworkDatagram nw(news.toUtf8(),QHostAddress("127.0.0.1"),12345);
            udp->writeDatagram(nw);
            news="R,"+ID+","+QString().number(ui->mapwidget->location.x())+","+QString().number(ui->mapwidget->location.y());
            QNetworkDatagram nww(news.toUtf8(),QHostAddress("127.0.0.1"),12345);
            udp->writeDatagram(nww);
           tm->stop();
           flag=0;
           return;
        }
        if(lc==next&&!rd.empty())
        {
            if(lc==ui->mapwidget->orderstart[ui->mapwidget->noworder])
                flag=1;
            lc=next;
            next=rd.front();
            rd.pop_front();
        }
        else
        {
            if(abs(lc.x()-next.x())<10)
            {
                lc=QPoint(next.x(),lc.y());
            }
            else if(lc.x()-next.x()>0)
                lc=QPoint(lc.x()-10,lc.y());
            else if(lc.x()==next.x())
            {

            }
            else if(lc.x()-next.x()<0)
            {
                lc=QPoint(lc.x()+10,lc.y());
            }
            if(abs(lc.y()-next.y())<10)
            {
                lc=QPoint(lc.x(),next.y());
            }
            else if(lc.y()-next.y()>0)
                lc=QPoint(lc.x(),lc.y()-10);
            else if(lc.y()==next.y())
            {

            }
            else if(lc.y()-next.y()<0)
            {
                lc=QPoint(next.x(),lc.y()+10);
            }
        }
        emit ui->mapwidget->chlocation(lc);
        emit ui->mapwidget->updateemit();
        QString news="C,"+ID+",courier,"+QString().number(lc.x())+","+QString().number(lc.y());
        QNetworkDatagram nw(news.toUtf8(),QHostAddress("127.0.0.1"),12345);
        udp->writeDatagram(nw);
    });
    tm->start(100);



}

void Carui::changeorder()
{
    if(ui->listWidget_4->currentItem()!=nullptr)
    {
    ui->locationButton_10->setEnabled(true);
    qDebug()<<"jjjjjjjj";
    int n=ui->listWidget_4->currentItem()->text().toInt();
    orderstart=ui->mapwidget->orderstart[n];
    orderfinal=ui->mapwidget->orderend[n];

    ui->mapwidget->noworder=n;
    emit ui->mapwidget->updateemit();
    }
}
